package com.example.springboot.service;

import com.example.springboot.document.ResInfoDoc;
import com.example.springboot.repository.ResInfoRepository;
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.support.PageableExecutionUtils;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author yuwl
 * @description
 * @since 2024-06-12 17:33
 */
@Service
public class ResInfoSearchService {

    @Autowired
    private ResInfoRepository resInfoRepository;

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    public void deleteIndex() throws Exception {
        if (elasticsearchRestTemplate.indexOps(ResInfoDoc.class).exists()) {
            elasticsearchRestTemplate.indexOps(ResInfoDoc.class).delete();
            System.out.println("索引 删除成功！");
        } else {
            System.out.println("索引 不存在！");
        }
    }

    public Boolean existsById(String id) throws Exception {
        return resInfoRepository.existsById(id);
    }

    public void save(ResInfoDoc resInfo) throws Exception {
        resInfoRepository.save(resInfo);
    }

    public void saveAll(List<ResInfoDoc> resInfoList) throws Exception {
        resInfoRepository.saveAll(resInfoList);
    }

    public ResInfoDoc findById(String id) throws Exception {
        return resInfoRepository.findById(id).get();
    }

    public void delete(String id) throws Exception {
        resInfoRepository.deleteById(id);
    }

    public void update(ResInfoDoc resInfo) throws Exception {
        resInfoRepository.save(resInfo);
    }

    public Page<ResInfoDoc> searchDocuments(String keyword, String upCompanyId, Date startDate, Date endDate, int page, int size) {
        // 页码转起始索引
        int pageIndex = Math.max(page - 1, 0);
        NativeSearchQueryBuilder  queryBuilder = new NativeSearchQueryBuilder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        if (!upCompanyId.isEmpty()) {
            boolQueryBuilder.must(QueryBuilders.termQuery("upcompanyid", upCompanyId));
        }
        RangeQueryBuilder dateRangeQuery = QueryBuilders.rangeQuery("tptime");
        if (startDate != null) {
            dateRangeQuery.gte(startDate.getTime());
        }
        if (endDate != null) {
            dateRangeQuery.lte(endDate.getTime());
        }
        if (startDate != null || endDate != null) {
            boolQueryBuilder.must(dateRangeQuery);
        }
        // 关键字查询
        if (!keyword.isEmpty()) {
            BoolQueryBuilder shouldQuery = QueryBuilders.boolQuery()
                    .should(QueryBuilders.multiMatchQuery(keyword, "resname", "abstractstr"))
                    .should(QueryBuilders.nestedQuery("fileDocs", QueryBuilders.matchQuery("fileDocs.filename", keyword), ScoreMode.None));
            boolQueryBuilder.must(shouldQuery);
        }

        if (boolQueryBuilder.hasClauses()) {
            queryBuilder.withQuery(boolQueryBuilder);
        } else {
            queryBuilder.withQuery(QueryBuilders.matchAllQuery());
        }

        NativeSearchQuery query = queryBuilder
                .withPageable(PageRequest.of(pageIndex, size))
                .build();
        System.out.println("DSL = " + query.getQuery().toString());

        SearchHits<ResInfoDoc> searchHits = elasticsearchRestTemplate.search(query, ResInfoDoc.class);

        List<ResInfoDoc> documents = searchHits.stream()
                .map(SearchHit::getContent)
                .collect(Collectors.toList());

        return PageableExecutionUtils.getPage(documents, PageRequest.of(pageIndex, size), searchHits::getTotalHits);
    }
}
